/*
 * Project Name: 26Nov2011-NSI_Assignment-0 
 * Package Name: cli
 * File Name: CommandLineHandler.java
 * Primary Type Name: CommandLineHandler
 * 
 * Created or edited by Cheng Ye on Nov 28, 2011
 */
package cli;

import java.io.PrintWriter;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;

// TODO: Auto-generated Javadoc
/**
 * The Class CommandLineHandler.
 */
public class CommandLineHandler {

	/** The parser. */
	private CommandLineParser parser;

	/** The options. */
	private Options options;

	/** The cli. */
	private CommandLine cli;

	/** The formatter. */
	private HelpFormatter formatter;

	/** The out. */
	private PrintWriter out;

	/**
	 * Instantiates a new command line handler.
	 */
	public CommandLineHandler() {
		init();
	}

	/**
	 * Prints the help.
	 */
	public void printHelp() {
		formatter.setSyntaxPrefix("Usage: ");
		formatter.printUsage(out, formatter.getWidth(),
				"java -jar fnet.jar [OPTIONS]... DATASET_FILE");
		formatter
				.printWrapped(
						out,
						formatter.getWidth(),
						"This program use a dataset (whose file path is specified in DATASET_FILE) to train or test (with -t or -T) the neural network. If no file is given, it will try to search for (in the same directory with the jar file) and use the default one named (\"dataset.txt\"). The program will automatically load network state from a file named \"default.network\" (in the same directory with the jar file) which contain network's last running state, otherwise a new network will be constructed.");
		out.println();
		formatter
				.printWrapped(out, formatter.getWidth(), "Avaiable arguments:");
		formatter.printOptions(out, formatter.getWidth(), options,
				formatter.getLeftPadding(), formatter.getDescPadding());
	}

	/**
	 * Inits the.
	 */
	private void init() {
		// create the command line parser
		parser = new PosixParser();
		// create the Options
		options = new Options();
		options.addOption("t", "train", false,
				"use the DATASET_FILE to train the network");
		options.addOption(
				"v",
				"verbose",
				false,
				"print detailed information, may decrease the performance; use with -t or -T option");
		options.addOption("T", "test", false,
				"test the network with given DATASET_FILE");
		options.addOption("h", "help", false, "print this help message");
		options.addOption(
				"l",
				"learning-rate",
				true,
				"specify the learning rate for the training; default value is 0.5; use with -tB -tM -tQ option");
		options.addOption(
				"e",
				"error-limit",
				true,
				"the training will stop when error rate is lower than this value; default value is 0.01; use with -t option");
		options.addOption(
				"r",
				"maximum-round",
				true,
				"maximum rounds for the training to run; set to 0 to remove the limit; default value is 5000; use with -t option");
		options.addOption("m", "momentum", true,
				"specify the momentum for the training; default value is 0.5; use with -tB option");
		options.addOption(
				"B",
				"back",
				false,
				"use backpropagation in training; use with -t option; it is used by default");
		options.addOption("M", "manhattan", false,
				"use manhattan update propagation in training; use with -t option");
		options.addOption("R", "resilient", false,
				"use resilent propagation in training; use with -t option");
		options.addOption("Q", "quick", false,
				"use quick propagation in training; use with -t option");
		options.addOption(
				"n",
				"neuron-num",
				true,
				"specify the number of neurons in the hidden layer; default value is 30; use this option will reset the network; use with -t option");
		
		// automatically generate help message
		formatter = new HelpFormatter();

		out = new PrintWriter(System.out, true);
	}

	/**
	 * Parses the.
	 * 
	 * @param args
	 *            the args
	 * @throws ParseException
	 *             the parse exception
	 */
	public void parse(String[] args) throws ParseException {
		cli = parser.parse(options, args);
	}

	/**
	 * Checks for option.
	 * 
	 * @param option
	 *            the option
	 * @return true, if successful
	 */
	public boolean hasOption(String option) {
		if (cli.hasOption(option)) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * Gets the data set.
	 * 
	 * @return the data set
	 */
	public String[] getDataSet() {
		return cli.getArgs();
	}

	/**
	 * Gets the opt arg.
	 * 
	 * @param option
	 *            the option
	 * @return the opt arg
	 */
	public String getOptArg(String option) {
		if (cli.hasOption(option)) {
			return cli.getOptionValue(option);
		} else {
			return null;
		}
	}

	/**
	 * Checks for opt in.
	 * 
	 * @param opts
	 *            the opts
	 * @return the int
	 */
	public int hasOptIn(String opts) {
		char[] copts = opts.toCharArray();
		int counter = 0;
		for (char c : copts) {
			if (cli.hasOption(c)) {
				counter++;
			}
		}
		return counter;
	}
}
